﻿using CoreDomain.BusinessCore;
using DomainService.IService;
using DomainService.IService.Sys;
using Infrastructure;
using Infrastructure.IRepository.Sys;
using Infrastructure.Repository.Sys;
using Model;
using Model.BusinessModel.InPut;
using Model.BusinessModel.OutPut;
using Model.BusinessModel.OutPut.sys;
using Model.DomainModel.Sys;
using System;
using Utility;
using Utility.Enum;

namespace DomainService.Service.Sys
{
    /// <summary>
    /// 角色服务接口实现
    /// </summary>
    public class SysRoleService : ISysRoleService
    {
        #region 构造实例化

        /// <summary>
        /// 角色底层仓储
        /// </summary>
        private readonly ISysRoleRepository _sysRoleRepository;

        /// <summary>
        /// 公司底层仓储
        /// </summary>
        private readonly ISysCorporationRepository _sysCorporationRepository;

        /// <summary>
        /// 系统底层仓储
        /// </summary>
        private readonly ISysSystemRepository _sysSystemRepository;

        /// <summary>
        /// 用户角色关系仓储
        /// </summary>
        private readonly ISysUserRoleRelationRepository _sysUserRoleRelationRepository;

        /// <summary>
        /// 用户角色关系仓储
        /// </summary>
        private readonly ISysMenuRoleRelationRepository _sysMenuRoleRelationRepository;

        /// <summary>
        /// 菜单顶层仓储
        /// </summary>
        private readonly ISysMenuRepository _sysMenuRepository;

        /// <summary>
        /// 按钮底层仓储
        /// </summary>
        private readonly ISysButtonRepository _sysButtonRepository;

        /// <summary>
        /// 按钮与角色关系
        /// </summary>
        private readonly ISysButtonRoleRepository _sysButtonRoleRepository;

        /// <summary>
        /// 基础服务
        /// </summary>
        private readonly IBaseService _baseService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sysRoleRepository"></param>
        /// <param name="sysCorporationRepository"></param>
        /// <param name="sysSystemRepository"></param>
        /// <param name="sysUserRoleRelationRepository"></param>
        /// <param name="sysMenuRoleRelationRepository"></param>
        /// <param name="sysMenuRepository"></param>
        /// <param name="sysButtonRoleRepository"></param>
        /// <param name="sysButtonRepository"></param>
        public SysRoleService(ISysRoleRepository sysRoleRepository, ISysCorporationRepository sysCorporationRepository, ISysSystemRepository sysSystemRepository, ISysUserRoleRelationRepository sysUserRoleRelationRepository, ISysMenuRoleRelationRepository sysMenuRoleRelationRepository, ISysMenuRepository sysMenuRepository, ISysButtonRoleRepository sysButtonRoleRepository, ISysButtonRepository sysButtonRepository, IBaseService baseService)
        {
            _sysRoleRepository = sysRoleRepository;
            _sysCorporationRepository = sysCorporationRepository;
            _sysSystemRepository = sysSystemRepository;
            _sysUserRoleRelationRepository = sysUserRoleRelationRepository;
            _sysMenuRoleRelationRepository = sysMenuRoleRelationRepository;
            _sysMenuRepository = sysMenuRepository;
            _sysButtonRoleRepository = sysButtonRoleRepository;
            _sysButtonRepository = sysButtonRepository;
            _baseService = baseService;
        }

        #endregion

        #region 业务逻辑

        /// <summary>
        /// 获取全部角色
        /// </summary>
        /// <returns></returns>
        public List<SysRoleOutPut> GetAllRoleTreeList(LoginOutPut loginModel)
        {
            var result = _baseService.GetAuthWhere(RuleTypeEnum.DataRowRule, "sy");
            string? authWhere = string.Empty;
            if (result.success) { authWhere = result.data[0]; }
            else
                ExceptionHelper.ThrowBusinessException(result.msg);

            var roleList = _sysRoleRepository.GetAllRoleTreeList(loginModel.CorporationKey, authWhere);
            var roleTreeList = RoleCore.GetRoleTreeList(roleList);
            return roleTreeList;
        }

        /// <summary>
        /// 新增角色
        /// </summary>
        /// <param name="sysRole">角色数据</param>
        public ReceiveStatus Insert(SysRole sysRole)
        {
            ReceiveStatus receiveStatus = new();
            var result = Validate(sysRole);
            sysRole.RoleType = (int)RoleTypeEnum.ordinaryRole;
            if (!result.success)
                return result;
            _sysRoleRepository.Insert(sysRole, BaseSqlRepository.sysRole_insertSql);
            return receiveStatus;
        }

        /// <summary>
        /// 修改角色
        /// </summary>
        /// <param name="sysRole">角色数据</param>
        public ReceiveStatus Update(SysRole sysRole)
        {
            ReceiveStatus receiveStatus = new();
            var model = _sysRoleRepository.GetByKey(sysRole.RoleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
            if (model == null)
                return ExceptionHelper.CustomException(string.Format("角色名称【{0}】不存存在或已删除!", sysRole.RoleName));
            if (sysRole.RoleType == (int)RoleTypeEnum.SuperRole)
                return ExceptionHelper.CustomException("超级管理员角色不能修改。");
            var result = Validate(sysRole);
            if (!result.success)
                return result;
            if (sysRole.RoleId == sysRole.Pid)
            {
                return ExceptionHelper.CustomException("不能设置当前角色为上级角色");
            }
            _sysRoleRepository.Update(sysRole, BaseSqlRepository.sysRole_updateSql);
            return receiveStatus;
        }

        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="sysRole">角色数据</param>
        /// <returns></returns>
        public ReceiveStatus Validate(SysRole sysRole)
        {
            ReceiveStatus receiveStatus = new ReceiveStatus();
            /*
            新增/修改前验证
            1、角色名称不能出现重复
            2、公司不能为空
            3、系统不能为空
            */

            if (string.IsNullOrWhiteSpace(sysRole.RoleName))
                return ExceptionHelper.CustomException("角色名称不能为空!");
            if (string.IsNullOrWhiteSpace(sysRole.CorporationKey.ToString()))
                return ExceptionHelper.CustomException("所属公司不能为空!");
            if (string.IsNullOrWhiteSpace(sysRole.SystemKey.ToString()))
                return ExceptionHelper.CustomException("所属系统不能为空!");

            var sysRoleModel = _sysRoleRepository.GetRoleByName(sysRole.CorporationKey, sysRole.SystemKey, sysRole.RoleName);
            if (sysRoleModel != null)
            {
                if (sysRoleModel.RoleName == sysRole.RoleName && sysRoleModel.RoleId != sysRole.RoleId)
                    return ExceptionHelper.CustomException(string.Format("角色名称【{0}】已存在,请重新输入!", sysRole.RoleName));
            }

            return receiveStatus;
        }

        /// <summary>
        /// 设置角色是否启用
        /// </summary>
        /// <param name="updateIsOpenInPut">修改模型</param>
        /// <returns></returns>
        public ReceiveStatus SetRoleIsOpen(UpdateIsOpenInPut updateIsOpenInPut)
        {
            ReceiveStatus receiveStatus = new();
            if (updateIsOpenInPut == null)
                return ExceptionHelper.CustomException("请选择角色");
            if (updateIsOpenInPut.Keys.Count == 0)
                return ExceptionHelper.CustomException("请选择角色");

            var roleKey = updateIsOpenInPut.Keys.FirstOrDefault(f => f == Const.OverallAuth_NoCloseRole.ToString());
            if (!string.IsNullOrWhiteSpace(roleKey))
            {
                var model = _sysRoleRepository.GetByKey(roleKey, BaseSqlRepository.sysRole_selectByKeySql);
                return ExceptionHelper.CustomException(string.Format("角色【{0}】为演示角色，禁止操作。", model.RoleName));
            }

            //写入数据库，加入事务
            TransactionHelper.ExecuteTransaction(() =>
            {
                _sysRoleRepository.SetRoleIsOpen(updateIsOpenInPut.Keys, updateIsOpenInPut.IsOpen);
            });

            return receiveStatus;
        }

        /// <summary>
        /// 获取树形结构角色数据
        /// </summary>
        /// <param name="corporationKey">公司key</param>
        /// <param name="systemKey">系统key</param>
        /// <returns></returns>
        public ReceiveStatus<TreeOutPut> GetRoleTree(string corporationKey, string? systemKey)
        {
            ReceiveStatus<TreeOutPut> receiveStatus = new ReceiveStatus<TreeOutPut>();
            if (string.IsNullOrWhiteSpace(corporationKey))
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("请选择公司！");

            if (!string.IsNullOrWhiteSpace(systemKey))
            {
                var systemModel = _sysSystemRepository.GetByKey(systemKey, BaseSqlRepository.sysSystem_selectByKeySql);
                if (systemModel == null)
                    return ExceptionHelper<TreeOutPut>.CustomExceptionData("系统不存在或已删除！");
            }

            var corporationModel = _sysCorporationRepository.GetByKey(corporationKey, BaseSqlRepository.sysCorporation_selectByKeySql);
            if (corporationModel == null)
                return ExceptionHelper<TreeOutPut>.CustomExceptionData("公司不存在或已删除！");

            var corporationSystemList = _sysRoleRepository.GetRoleList(corporationKey, systemKey);

            List<TreeOutPut> list =
            [
                new TreeOutPut
                {
                    key = corporationModel.CorporationKey,
                    pKey = "",
                    label = corporationModel.CorporationName,
                },
            ];
            list.AddRange(corporationSystemList);

            //递归获取角色树
            var tree = list.ConvertTreeData();
            receiveStatus.data = tree;
            return receiveStatus;
        }

        /// <summary>
        /// 保存角色权限--菜单权限
        /// </summary>
        /// <param name="roleMenuExend">角色和菜单模型</param>
        /// <param name="userId">操作人员id</param>
        public ReceiveStatus SaveRoleAuthority(RoleMenuInput roleMenuExend, string userId)
        {
            ReceiveStatus receiveStatus = new();
            //获取角色
            var roleModel = _sysRoleRepository.GetByKey(roleMenuExend.roleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
            if (roleModel == null)
                return ExceptionHelper.CustomException(string.Format("角色id为【{0}】的角色不存在", roleMenuExend.roleId));
            var dateTime = DateTime.Now;

            List<SysMenuRoleRelation> list = new();
            //全选菜单
            foreach (var item in roleMenuExend.menuIds)
            {
                SysMenuRoleRelation sysMenuRoleRelation = new SysMenuRoleRelation
                {
                    CreateTime = dateTime,
                    RoleId = roleMenuExend.roleId,
                    CreateUser = userId,
                    IsHalfSelected = false,
                    MenuId = item,
                };
                list.Add(sysMenuRoleRelation);
            }

            //半选菜单
            foreach (var item in roleMenuExend.isHalfMenuIds)
            {
                SysMenuRoleRelation sysMenuRoleRelation = new SysMenuRoleRelation
                {
                    CreateTime = dateTime,
                    RoleId = roleMenuExend.roleId,
                    CreateUser = userId,
                    IsHalfSelected = true,
                    MenuId = item,
                };
                list.Add(sysMenuRoleRelation);
            }

            TransactionHelper.ExecuteTransaction(() =>
            {
                _sysMenuRoleRelationRepository.DeleteByRoleId(roleMenuExend.roleId);
                _sysMenuRoleRelationRepository.BatchInsert(list);
            });
            return receiveStatus;
        }

        /// <summary>
        /// 保存角色权限--按钮权限
        /// </summary>
        /// <param name="RoleButtonInput">角色和按钮模型</param>
        /// <param name="userId">操作人员id</param>
        public ReceiveStatus SaveRoleButtonAuthority(RoleButtonInput roleButtonExend, string userId)
        {
            ReceiveStatus receiveStatus = new();
            //获取角色
            var roleModel = _sysRoleRepository.GetByKey(roleButtonExend.roleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
            if (roleModel == null)
                return ExceptionHelper.CustomException(string.Format("角色id为【{0}】的角色不存在", roleButtonExend.roleId));
            var dateTime = DateTime.Now;

            var buttonList = _sysButtonRepository.GetButtonByButtonId(roleButtonExend.buttonIds);

            List<SysButtonRole> list = new();
            //全选菜单
            foreach (var item in roleButtonExend.buttonIds)
            {
                SysButtonRole sysMenuRoleRelation = new SysButtonRole
                {
                    ButtonRoleId = Guid.NewGuid().ToString(),
                    ButtonId = item,
                    CreateTime = dateTime,
                    RoleId = roleButtonExend.roleId,
                    CreateUser = userId,
                    MenuId = buttonList.Where(f => f.ButtonId == item).FirstOrDefault()?.MenuId,
                };
                list.Add(sysMenuRoleRelation);
            }

            TransactionHelper.ExecuteTransaction(() =>
            {
                _sysButtonRoleRepository.DeleteByRoleId(roleButtonExend.roleId);
                _sysButtonRoleRepository.BatchInsert(list);
            });
            return receiveStatus;
        }

        /// <summary>
        /// 绑定角色用户
        /// </summary>
        /// <param name="roleUserInput">角色和用户模型</param>
        /// <param name="userId">操作人员id</param>
        public ReceiveStatus BindRoleUser(RoleUserInput roleUserInput, string userId)
        {
            ReceiveStatus receiveStatus = new();
            //获取角色
            var roleModel = _sysRoleRepository.GetByKey(roleUserInput.roleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
            if (roleModel == null)
                return ExceptionHelper.CustomException(string.Format("角色id为【{0}】的角色不存在", roleUserInput.roleId));
            var dateTime = DateTime.Now;

            List<SysUserRoleRelation> list = new();
            //组装角色和用户关系数据
            foreach (var item in roleUserInput.userId)
            {
                SysUserRoleRelation sysUserRoleRelation = new SysUserRoleRelation
                {
                    RoleId = roleUserInput.roleId,
                    UserId = item,
                    CreateTime = dateTime,
                    CreateUser = userId,
                };
                list.Add(sysUserRoleRelation);
            }

            TransactionHelper.ExecuteTransaction(() =>
            {
                _sysUserRoleRelationRepository.DeleteByRoleId(roleUserInput.roleId);
                _sysUserRoleRelationRepository.BatchInsert(list);
            });
            return receiveStatus;
        }

        /// <summary>
        /// 根据角色id获取权限菜单
        /// </summary>
        /// <param name="roleId">角色id</param>
        /// <param name="corporationKey">公司key</param>
        /// <param name="isContainSubordinate">是否包含下级角色</param>
        /// <returns>返回角色所属菜单key</returns>
        public ReceiveStatus<MenuOrRoleOutPut> GetMenuKeyByRoleId(int roleId, bool isContainSubordinate, string corporationKey)
        {
            ReceiveStatus<MenuOrRoleOutPut> receiveStatus = new ReceiveStatus<MenuOrRoleOutPut>();
            List<MenuOrRoleOutPut> selectedItem = new();

            if (string.IsNullOrWhiteSpace(corporationKey))
                return ExceptionHelper<MenuOrRoleOutPut>.CustomExceptionData("请先登录");
            if (roleId > 0)
            {
                //获取角色
                var roleModel = _sysRoleRepository.GetByKey(roleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
                if (roleModel == null)
                    return ExceptionHelper<MenuOrRoleOutPut>.CustomExceptionData(string.Format("角色id为【{0}】的角色不存在", roleId));

                //当前角色菜单
                var currentRoleMenuList = _sysMenuRoleRelationRepository.GetSysMenuRoleRelationByRoleId(new List<int> { roleId }).Where(f => f.IsHalfSelected == false).ToList();
                foreach (var item in currentRoleMenuList)
                {
                    MenuOrRoleOutPut MenuOrRoleOutPut = new()
                    {
                        subordinateRoleMenu = false,
                        roleKey = roleId,
                        menuKey = item.MenuId ?? string.Empty
                    };
                    selectedItem.Add(MenuOrRoleOutPut);
                }
                if (isContainSubordinate)
                {
                    //递归获取下级角色菜单
                    var roleIdList = RoleCore.GetChildrenRoleById(roleId, corporationKey, Const.OverallAuth_SystemKey);
                    var menuRoleList = _sysMenuRoleRelationRepository.GetSysMenuRoleRelationByRoleId(roleIdList).Where(f => f.IsHalfSelected == false).ToList();
                    foreach (var item in menuRoleList)
                    {
                        MenuOrRoleOutPut MenuOrRoleOutPut = new()
                        {
                            subordinateRoleMenu = true,
                            roleKey = roleId,
                            menuKey = item.MenuId ?? string.Empty
                        };
                        selectedItem.Add(MenuOrRoleOutPut);
                    }
                }
            }
            receiveStatus.data = selectedItem;
            receiveStatus.msg = "获取成功";
            return receiveStatus;
        }


        /// <summary>
        /// 根据角色id获取权限按钮
        /// </summary>
        /// <param name="roleId">角色id</param>
        /// <param name="corporationKey">公司key</param>
        /// <param name="isContainSubordinate">是否包含下级角色</param>
        /// <returns>返回角色所属按钮key</returns>
        public ReceiveStatus<ButtonOrRoleOutPut> GetButtonKeyByRoleId(int roleId, bool isContainSubordinate, string corporationKey)
        {
            ReceiveStatus<ButtonOrRoleOutPut> receiveStatus = new ReceiveStatus<ButtonOrRoleOutPut>();
            List<ButtonOrRoleOutPut> selectedItem = new();

            if (string.IsNullOrWhiteSpace(corporationKey))
                return ExceptionHelper<ButtonOrRoleOutPut>.CustomExceptionData("请先登录");
            if (roleId > 0)
            {
                //获取角色
                var roleModel = _sysRoleRepository.GetByKey(roleId.ToString(), BaseSqlRepository.sysRole_selectByKeySql);
                if (roleModel == null)
                    return ExceptionHelper<ButtonOrRoleOutPut>.CustomExceptionData(string.Format("角色id为【{0}】的角色不存在", roleId));

                //当前角色菜单按钮
                var currentRoleMenuButtonList = _sysButtonRoleRepository.GetButtonRoleByRoleId(new List<int> { roleId }).ToList();
                foreach (var item in currentRoleMenuButtonList)
                {
                    ButtonOrRoleOutPut ButtonOrRoleOutPut = new()
                    {
                        subordinateRoleButton = false,
                        roleKey = roleId,
                        buttonKey = item.ButtonId ?? string.Empty
                    };
                    selectedItem.Add(ButtonOrRoleOutPut);
                }
                if (isContainSubordinate)
                {
                    //递归获取下级角色菜单按钮
                    var roleIdList = RoleCore.GetChildrenRoleById(roleId, corporationKey, Const.OverallAuth_SystemKey);
                    var menuRoleList = _sysButtonRoleRepository.GetButtonRoleByRoleId(roleIdList).ToList();
                    foreach (var item in menuRoleList)
                    {
                        ButtonOrRoleOutPut ButtonOrRoleOutPut = new()
                        {
                            subordinateRoleButton = true,
                            roleKey = roleId,
                            buttonKey = item.ButtonId ?? string.Empty
                        };
                        selectedItem.Add(ButtonOrRoleOutPut);
                    }
                }
            }
            receiveStatus.data = selectedItem;
            receiveStatus.msg = "获取成功";
            return receiveStatus;
        }
        #endregion
    }
}
